<template>
  <div
      class="vk-input"
      :class="{
    [`vk-input--${type}`]: type,
    [`vk-input--${size}`]: size,
    'is-disabled': disabled,
    'is-prepend': $slots.prepend,
    'is-append': $slots.append,
    'is-prefix': $slots.prefix,
    'is-suffix': $slots.suffix,
    'is-focus': isFocus
  }">
    <!-- input -->
    <template v-if="type !== 'textarea'">
      <div v-if="$slots.prepend" class="vk-input__prepend">
        <slot name="prepend"></slot>
      </div>
      <div class="vk-input__wrapper">
        <span v-if="$slots.prefix" class="vk-input__prefix">
          <slot name="prefix"></slot>
        </span>
        <input
            ref="inputRef"
            class="vk-input__inner"
            :type="showPassword ? (passwordVisible ? 'text' : 'password') : type"
            v-bind="$attrs"
            :disabled="disabled"
            :clearable="clearable"
            :readonly="readonly"
            :autocomplete="autocomplete"
            :autofocus="autofocus"
            v-model="innerValue"
            @input="handleInput"
            @change="handleChange"
            @focus="handleFocus"
            @blur="handleBlur"
        />
        <!-- suffix slot -->
        <span v-if="$slots.suffix || showClear || showPasswordArea" class="vk-input__suffix" @click="keepFocus">
          <slot name="suffix"/>
          <Icon
              icon="circle-xmark"
              v-if="showClear"
              class="vk-input__clear"
              @click="clear"
              @mousedown.prevent="NOOP"
          />
          <Icon
              icon="eye"
              v-if="showPasswordArea && passwordVisible"
              class="vk-input__password"
              @click="togglePasswordVisible"
          />
          <Icon
              icon="eye-slash"
              v-if="showPasswordArea && !passwordVisible"
              class="vk-input__password"
              @click="togglePasswordVisible"
          />
      </span>
      </div>
      <!-- append slot -->
      <div v-if="$slots.append" class="vk-input__append">
        <slot name="append"/>
      </div>
    </template>
    <!-- textarea -->
    <template v-else>
      <textarea
          class="vk-textarea__wrapper"
          v-bind="$attrs"
          ref="inputRef"
          :disabled="disabled"
          :readonly="readonly"
          :autocomplete="autocomplete"
          :placeholder="placeholder"
          :autofocus="autofocus"
          :form="form"
          v-model="innerValue"
          @input="handleInput"
          @change="handleChange"
          @focus="handleFocus"
          @blur="handleBlur"
      />
    </template>
  </div>
</template>

<script setup lang="ts">
import {computed, Ref, ref, nextTick, watch, inject} from "vue";
import {formItemContextKey} from "../Form/types"
import type {InputEmits, InputProps} from "@/components/Input/types";

defineOptions({
  name: 'VkInput',
  inheritAttrs: false
})
const NOOP = () => {
}
const props = withDefaults(defineProps<InputProps>(), {type: 'text', autocomplete: 'off'})
const emits = defineEmits<InputEmits>()
const innerValue = ref(props.modelValue)
const isFocus = ref(false)
const inputRef = ref() as Ref<HTMLInputElement>
const showClear = computed(() => props.clearable && !props.disabled && !!innerValue.value && isFocus.value)
const showPasswordArea = computed(() => props.showPassword && !props.disabled && !!innerValue.value)
const passwordVisible = ref(false)
const formItemContext = inject(formItemContextKey)

const runValidation = (trigger?:string)=>{
  formItemContext?.validate(trigger).catch((e)=>console.log(e.errors))
}

watch(() => props.modelValue,
    (newValue) => {
      innerValue.value = newValue
    }
)
const togglePasswordVisible = () => {
  passwordVisible.value = !passwordVisible.value
}
const handleInput = (e: Event) => {
  const value = e.target?.value
  emits('update:modelValue', value)
  emits('input', value)
  runValidation('input')
}
const keepFocus = async () => {
  await nextTick()
  inputRef.value.focus()
}
const clear = () => {
  innerValue.value = ''
  emits('update:modelValue', '')
  emits('change', '')
  emits('input', '')
  emits('clear')
}
const handleChange = (e: Event) => {
  emits('change', innerValue.value)
  runValidation('change')
}
const handleFocus = (event: FocusEvent) => {
  isFocus.value = true
  emits('focus', event)
}
const handleBlur = (event: FocusEvent) => {
  runValidation('blur')
  isFocus.value = false
  emits('blur', event)
}
defineExpose({
  ref: inputRef
})
</script>

<style scoped>
@import "style.css";
</style>
